#ifndef __SGL_CORE_H__
#define __SGL_CORE_H__

#include <stdint.h>
#include "sgl_conf.h"
#include "sgl_list.h"
#include "sgl_math.h"
#include "sgl_misc.h"


#if _WIN32 || WIN32
#define _const __attribute__((section (".const")))
#else
#define _const  const
#endif

typedef enum sgl_event_type {
    SGL_EVENT_NULL = 0,
    SGL_EVENT_NORMAL = 1,
    SGL_EVENT_PRESSED = 2,
    SGL_EVENT_RELEASED = 3,
    SGL_EVENT_LONG_PRESSED = 4,
    SGL_EVENT_TURN_ON,
    SGL_EVENT_TURN_OFF,
    SGL_EVENT_UNKNOW,
    SGL_EVENT_FORCE_DRAW, //TODO: add force draw event callback
    SGL_EVENT_ALL = 255,

}sgl_event_type_e;


typedef enum sgl_align_type {
    SGL_ALIGN_TOP_MID,
    SGL_ALIGN_TOP_LEFT,
    SGL_ALIGN_TOP_RIGHT,
    SGL_ALIGN_CENTER_MID,
    SGL_ALIGN_CENTER_LEFT,
    SGL_ALIGN_CENTER_RIGHT,
    SGL_ALIGN_BOT_MID,
    SGL_ALIGN_BOT_LEFT,
    SGL_ALIGN_BOT_RIGHT,
    SGL_ALIGN_TOP,
    SGL_ALIGN_CENTER,
    SGL_ALIGN_BOT,
    SGL_ALIGN_LEFT,
    SGL_ALIGN_MID,
    SGL_ALIGN_RIGHT,

}sgl_align_type_e;

typedef enum sgl_obj_type {
    SGL_OBJ_UNKNOW = 0,
    SGL_OBJ_BUTTON = 1,
    SGL_OBJ_LABEL = 2,
    SGL_OBJ_SWITCH,
    SGL_OBJ_BATTERY,
    SGL_OBJ_PIXELMAP,
    SGL_OBJ_TABVIEW,
    SGL_OBJ_CHECKBOX,
    SGL_OBJ_RADIOBUTTON,
    SGL_OBJ_COMBOX,
    SGL_OBJ_MSGBOX,
    SGL_OBJ_NUMBER,
    SGL_OBJ_PROGRESSBAR,
    
}sgl_obj_type_e;


typedef struct sgl_pos {
    int16_t x;
    int16_t y;
}sgl_pos_t;

typedef struct sgl_size {
    int16_t w;
    int16_t h;
}sgl_size_t;

typedef struct sgl_rect {
    int16_t x1;
    int16_t y1;
    int16_t x2;
    int16_t y2;
}sgl_rect_t;

typedef union {
    struct {
        uint8_t blue;
        uint8_t green;
        uint8_t red;
        uint8_t alpha;
    };
    uint32_t full;
}sgl_color32_t;

typedef union {
    struct {
        uint16_t blue : 5;
        uint16_t green : 6;
        uint16_t red : 5;
    };
    uint16_t full;
}sgl_color16_t;

typedef union {
    struct {
        uint8_t blue : 2;
        uint8_t green : 3;
        uint8_t red : 3;
    };
    uint8_t full;
}sgl_color8_t;

#if (SGL_CONFIG_PANEL_PIXEL_DEPTH == 32)
#define sgl_color_t sgl_color32_t
#elif (SGL_CONFIG_PANEL_PIXEL_DEPTH == 16)
#define sgl_color_t sgl_color16_t
#elif (SGL_CONFIG_PANEL_PIXEL_DEPTH == 8)
#define sgl_color_t sgl_color8_t
#endif

typedef struct sgl_surf {
    sgl_color_t *fb;
    sgl_size_t  size;
    
}sgl_surf_t;

typedef struct sgl_style {
    sgl_color_t body_color;
    sgl_color_t text_color;
    uint16_t radius;

}sgl_style_t;


typedef struct sgl_obj {
    sgl_pos_t  pos;
    sgl_size_t size;
    sgl_rect_t area;
    sgl_style_t style;
    void (*event_fn)(struct sgl_obj *obj, void *data);
    void *event_data;
    sgl_event_type_e ev_stat;
    struct sgl_obj *parent;
    sgl_list_node_t node;
    sgl_list_node_t dirty;
    sgl_obj_type_e  obj_type;
    bool selected;
    bool clip;
    
}sgl_obj_t;

typedef struct sgl_anim {
    sgl_list_node_t node;
    sgl_obj_t *obj;
    sgl_pos_t pos_start;
    sgl_pos_t pos_end;
    uint64_t  tick;
    uint32_t  interval;//ms
    uint32_t  times;
    void (*anim_cb)(struct sgl_anim *anim, void *data);
    void *anim_cb_data;
    
}sgl_anim_t;

typedef struct sgl_event_pos {
    int16_t x;
    int16_t y;
    sgl_event_type_e type;

}sgl_event_pos_t;

typedef struct sgl_font_table {
    int bitmap_index;
    int8_t height;
    int8_t width;
    int8_t ofs_x;
    int8_t ofs_y;

}sgl_font_table_t;


typedef struct sgl_font {
    const uint8_t  *bitmap;
    const sgl_font_table_t  *table;
    uint16_t  font_table_size;
    uint16_t  font_height;

}sgl_font_t;

typedef struct sgl_icon {
    const uint8_t  *bitmap;
    uint16_t width;
    uint16_t height;

}sgl_icon_t;

static inline sgl_color_t sgl_int2color(uint32_t color)
{
    return *(sgl_color_t*)(&color);
}

static inline sgl_color_t sgl_rgb2color(uint8_t red, uint8_t green, uint8_t blue)
{
    sgl_color_t color = { .blue=blue, .green=green, .red=red,};
    return color;
}


/**
 * sgl obj api
 * 
*/
void sgl_obj_set_pos(sgl_obj_t *obj, int16_t x, int16_t y);
sgl_pos_t sgl_obj_get_pos(sgl_obj_t *obj);
void sgl_obj_set_pos_x(sgl_obj_t *obj, int16_t x);
int16_t sgl_obj_get_pos_x(sgl_obj_t *obj);
void sgl_obj_set_pos_y(sgl_obj_t *obj, int16_t y);
int16_t sgl_obj_get_pos_y(sgl_obj_t *obj);
void sgl_obj_set_size(sgl_obj_t *obj, int16_t width, int16_t height);
void sgl_obj_set_size_w(sgl_obj_t *obj, int16_t width);
void sgl_obj_set_size_h(sgl_obj_t *obj, int16_t height);
void sgl_obj_set_style(sgl_obj_t *obj, sgl_style_t style);
void sgl_obj_set_body_color(sgl_obj_t *obj, sgl_color_t color);
void sgl_obj_set_text_color(sgl_obj_t *obj, sgl_color_t color);
void sgl_obj_set_radius(sgl_obj_t *obj, int radius);
void sgl_obj_set_parent(sgl_obj_t *obj, sgl_obj_t *parent);
void sgl_obj_set_align(sgl_obj_t *obj, sgl_align_type_e type);
void sgl_obj_set_event_cb(sgl_obj_t *obj, void (*event)(sgl_obj_t *, void *), void *data);
void sgl_obj_event_cb(sgl_obj_t *obj);
void sgl_obj_set_event_status(sgl_obj_t *obj, sgl_event_type_e status);
sgl_event_type_e sgl_obj_get_event_status(sgl_obj_t *obj);
bool sgl_obj_draw_valid(sgl_obj_t *obj);
bool sgl_obj_event_active(sgl_obj_t* obj, int x, int y);
void sgl_obj_set_selected(sgl_obj_t* obj, bool status);
void sgl_obj_event_click(sgl_obj_t *obj);
void sgl_obj_event_press(sgl_obj_t *obj);
void sgl_obj_event_release(sgl_obj_t *obj);

sgl_pos_t sgl_get_align_pos(sgl_size_t *parent_size, sgl_size_t *size, sgl_align_type_e type);


/**
 *  sgl event queue api
*/
bool sgl_event_queue_is_empty(void);
bool sgl_event_queue_is_full(void);
void sgl_event_queue_push(sgl_event_pos_t event);
sgl_event_pos_t sgl_event_queue_pop(void);
void sgl_task_handler(void);


void sgl_event_set_device_pos(sgl_event_pos_t event);
sgl_event_pos_t sgl_event_get_device_pos(void);


/**
 * sgl obj dirty list api
*/
void sgl_obj_add_dirty_list(sgl_obj_t *obj);
void sgl_obj_del_dirty_list(sgl_obj_t *obj);
sgl_list_node_t* sgl_obj_get_dirty_list_head(void);

/**
 * 
*/
void sgl_obj_add_src_act_list(sgl_obj_t *obj);
void sgl_obj_del_src_act_list(sgl_obj_t *obj);
sgl_list_node_t* sgl_obj_get_src_act_list_head(void);

sgl_obj_t* sgl_scr_active(void);
void sgl_set_scr_active_color(sgl_color_t color);
sgl_color_t sgl_get_scr_active_color(void);


/**
 * sgl anim api
*/
void sgl_tick_inc(uint32_t ms);
void sgl_anim_set_anim_cb(sgl_anim_t *anim, void (*anim_cb)(struct sgl_anim *, void *), void* data);
void sgl_anim_set_times(sgl_anim_t *anim, uint32_t  times);
void sgl_anim_set_interval(sgl_anim_t *anim, uint32_t  interval);
void sgl_anim_bind_obj(sgl_anim_t *anim, sgl_obj_t *obj);
void sgl_anim_exec(sgl_anim_t *anim);



void* sgl_alloc(int size);

int sgl_init(void);


#endif //__SGL_CORE_H__
